package pl.makimo.fuzzy.linguistics;

import java.util.List;

import pl.makimo.fuzzy.norms.MinNorm;
import pl.makimo.fuzzy.sets.CompoundFuzzySet;
import pl.makimo.fuzzy.sets.CompoundFuzzySetFactory;
import pl.makimo.fuzzy.sets.FuzzySet;

public class QualityMeasures {
	public static <T> double T1(Summary<T> summary) {
		if (summary.quantifier.relative) {
			if (summary.qualifier == null) {				
				return (Double)summary.quantifier.set.value(summary.summarizer.set.cardinality() / summary.summarizer.set.crispCardinality());
			} else {
				FuzzySet<T> compound = CompoundFuzzySetFactory.make(summary.summarizer.set, summary.qualifier.set, summary.type1norm, summary.type2norm);

				return (Double)summary.quantifier.set.value(compound.cardinality() / summary.qualifier.set.cardinality());
			}
		} else {
			return (Double)summary.quantifier.set.value(summary.summarizer.set.cardinality());
		}
	}
	
	public static <T> double T2(Summary<T> summary) {
		double product = 1.0;
		
		List<Summarizer<T>> summarizers = summary.getSingleSummarizers();
		
		for (Summarizer<T> summarizer : summarizers) {
			product = product * summarizer.set.in();
		}
		
		return Math.abs(1 - Math.pow(product, 1.0 / (double)summarizers.size()));
	}	
	
	public static <T> double T3(Summary<T> summary) {
		if (summary.quantifier.relative) {
			if (summary.qualifier == null) {
				return summary.summarizer.set.support().cardinality() / (double)summary.summarizer.set.crispCardinality();
			} else {
				FuzzySet<T> compound = CompoundFuzzySetFactory.make(summary.summarizer.set, summary.qualifier.set, summary.type1norm, summary.type2norm);
				double qualifierCardinality = summary.qualifier.set.support().cardinality();
				
				return qualifierCardinality > 0 ? (compound.support().cardinality() / qualifierCardinality) : 0.0;
			}
		} else {
			// not supported
			return 0.0;
		}
	}	
	
	public static <T> double T4(Summary<T> summary) {
		double product = 1.0;
		
		for (Summarizer<T> summarizer : summary.getSingleSummarizers()) {
			product = product * ((double)summarizer.set.support().cardinality() / (double)summarizer.set.crispCardinality());
		}
		
		return Math.abs(product - T3(summary));
	}	
	
	public static <T> double T5(Summary<T> summary) {
		return 2.0 * Math.pow(0.5, summary.getSingleSummarizers().size());
	}	
	
	public static <T> double T6(Summary<T> summary) {
		return 1.0 - summary.quantifier.set.in();
	}	
	
	public static <T> double T7(Summary<T> summary) {
		if (summary.quantifier.relative == true) {
			return 1.0 - summary.quantifier.set.cardinality();
		} else {
			return 1.0 - (summary.quantifier.set.cardinality() / summary.tuples.cardinality());
		}
	}	
	
	public static <T> double T8(Summary<T> summary) {
		double product = 1.0;
		
		List<Summarizer<T>> summarizers = summary.getSingleSummarizers();
		
		for (Summarizer<T> summarizer : summarizers) {
			product = product * (summarizer.set.cardinality() / summarizer.set.crispCardinality());
		}
		
		return Math.abs(1 - Math.pow(product, 1.0 / (double)summarizers.size()));
	}	
	
	public static <T> double T9(Summary<T> summary) {
		if (summary.qualifier == null) {
			return 0.0;			
		}
		
		double product = 1.0;
		
		List<Qualifier<T>> qualifiers = summary.getSingleQualifiers();
		
		for (Qualifier<T> qualifier : qualifiers) {
			product = product * qualifier.set.in();
		}
		
		return Math.abs(1 - Math.pow(product, 1.0 / (double)qualifiers.size()));
	}	
	
	public static <T> double T10(Summary<T> summary) {
		if (summary.qualifier == null) {
			return 0.0;			
		}
		
		double product = 1.0;
		
		List<Qualifier<T>> qualifiers = summary.getSingleQualifiers();
		
		for (Qualifier<T> qualifier : qualifiers) {
			product = product * (qualifier.set.cardinality() / qualifier.set.crispCardinality());
		}
		
		return Math.abs(1 - Math.pow(product, 1.0 / (double)qualifiers.size()));
	}	
	
	public static <T> double T11(Summary<T> summary) {
		if (summary.qualifier == null) {
			return 0.0;	
		}
		
		return 2.0 * Math.pow(0.5, summary.getSingleQualifiers().size());
	}	
}
